package com.ting.encrypt.init;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ting.encrypt.annotation.EncryptField;
import com.ting.encrypt.annotation.SensitiveEncryptEnabled;
import com.ting.encrypt.config.EncryptConfig;
import com.ting.encrypt.utils.ColumnNameUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 收集需要加密的类 获取加了SensitiveEncryptEnabled注解的类，解析获取到表名，需要加密的字段名，字段对应的加密算法
 * 获取表名：如果类上加了@TableName注解，并且注解有value值，则表名为value值，否则将类型转化成下划线作为表名（如类名为UserInfo，则表名为user_info）
 * 获取字段名：如果字段上加了@TableField注解，并且注解有value值，则字段名为value值，否则将类的属性名转化成下划线作为表名（如属性名为userName，则字段名为user_name）
 * TODO 目前只做机密性，完整性后续考虑
 */
@Slf4j
@Component
@Configuration
public class ScanEncryptClasses implements ApplicationContextAware {

    private Environment environment;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.environment = applicationContext.getEnvironment();

        Map<String, Object> encryptBeanMap =
                applicationContext.getBeansWithAnnotation(SensitiveEncryptEnabled.class);
        if (encryptBeanMap == null || encryptBeanMap.size() == 0) {
            return;
        }

        for (Map.Entry<String, Object> entry : encryptBeanMap.entrySet()) {
            // 获取表名
            Object entity = entry.getValue();
            Class<?> aClass = entity.getClass();
            TableName tableNameAnnotation = aClass.getAnnotation(TableName.class);
            String tableName = tableNameAnnotation != null ? tableNameAnnotation.value() : "";
            // 如果没有设置表名，则类名转成下划线方式作为表名
            if (StringUtils.isBlank(tableName)) {
                String className = aClass.getName();
                tableName =
                        ColumnNameUtil.underlineByhump(
                                ColumnNameUtil.lowerFirstCase(
                                        className.substring(className.lastIndexOf(".") + 1)));
            }

//                // 获取要完整性加密的字段
//                DataIntegrityEnabled dataIntegrityEnabled = aClass.getAnnotation(DataIntegrityEnabled.class);
//                if(dataIntegrityEnabled != null) {
//                    DataIntegrityEntity dataIntegrityEntity = new DataIntegrityEntity();
//                    dataIntegrityEntity.setBaseDataIntegrity(dataIntegrityEnabled.encryptType());
//                    EncryptConfig.setDataIntegrityFieldMap(tableName,dataIntegrityEntity);
//                }

            // 获取表中要加密的字段
            Field[] declaredFields = aClass.getDeclaredFields();

            // 获取要完整性加密的字段
//                List<DataIntegrityFieldEntity> dataIntegrityFields = new ArrayList<>();
            Map<String, EncryptField> encryptFieldsInfoMap = new HashMap<>();
            for (Field declaredField : declaredFields) {
                EncryptField annotation = declaredField.getAnnotation(EncryptField.class);
                if (ObjectUtils.isEmpty(annotation)) {
                    continue;
                }

                // 获取sql表中对应的字段名
                String tableFieldName = "";
                TableField tableFieldAnnotation =
                        declaredField.getAnnotation(TableField.class);

                tableFieldName = ObjectUtils.isEmpty(tableFieldAnnotation)
                        ? ColumnNameUtil.underlineByhump(declaredField.getName())
                        : tableFieldAnnotation.value();

                encryptFieldsInfoMap.put(tableFieldName, annotation);

//                    DataIntegrityField dataIntegrityField = declaredField.getAnnotation(DataIntegrityField.class);
//                    if(dataIntegrityField != null) {
//                        dataIntegrityFields.add(new DataIntegrityFieldEntity(dataIntegrityField.order(),tableFieldName));
//                    }
            }

            EncryptConfig.setEncryptTableInfoMap(tableName, encryptFieldsInfoMap);

            log.info("加密的表tableName={},加密的字段={}",tableName, JSON.toJSONString(encryptFieldsInfoMap));
//            if (StringUtils.isNotBlank(tableName)) {
//                EncryptConfig.setEncryptTableInfoMap(tableName, encryptFieldsInfoMap);
//
//                    if(dataIntegrityEnabled != null
//                            && CollectionUtils.isNotEmpty(dataIntegrityFields)) {
//
//                        List<String> fieldList = dataIntegrityFields.stream().map(fields -> fields.getFieldName()).collect(Collectors.toList());
//                        DataIntegrityEntity dataIntegrityEntity = new DataIntegrityEntity();
//                        dataIntegrityEntity.setBaseDataIntegrity(dataIntegrityEnabled.encryptType());
//                        dataIntegrityEntity.setFieldNames(fieldList);
//                        EncryptConfig.setDataIntegrityFieldMap(tableName,dataIntegrityEntity);
//                    }
//            }
        }
    }
}
